package com.codeoss.module.stock.service.impl;

import java.math.BigDecimal;
import java.util.List;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.codeoss.framework.service.impl.BaseService;
import com.codeoss.framework.util.DateUtil;
import com.codeoss.module.ir.service.IIrDocTypeService;
import com.codeoss.module.ir.service.IIrSequenceService;
import com.codeoss.module.purchase.model.PurchaseOrder;
import com.codeoss.module.purchase.model.PurchaseOrderLine;
import com.codeoss.module.purchase.service.IPurchaseOrderLineService;
import com.codeoss.module.purchase.service.IPurchaseOrderService;
import com.codeoss.module.sale.model.SaleReturn;
import com.codeoss.module.sale.model.SaleReturnLine;
import com.codeoss.module.sale.service.ISaleReturnLineService;
import com.codeoss.module.sale.service.ISaleReturnService;
import com.codeoss.module.stock.dao.StockInMapper;
import com.codeoss.module.stock.model.StockIn;
import com.codeoss.module.stock.model.StockInConfirm;
import com.codeoss.module.stock.model.StockInLine;
import com.codeoss.module.stock.model.StockOut;
import com.codeoss.module.stock.model.StockOutLine;
import com.codeoss.module.stock.model.StockTransaction;
import com.codeoss.module.stock.service.IStockInConfirmService;
import com.codeoss.module.stock.service.IStockInLineService;
import com.codeoss.module.stock.service.IStockInService;
import com.codeoss.module.stock.service.IStockLocatorService;
import com.codeoss.module.stock.service.IStockOutLineService;
import com.codeoss.module.stock.service.IStockOutService;
import com.codeoss.module.stock.service.IStockStorageService;
import com.codeoss.module.stock.service.IStockTransactionService;

@Service
public class StockInService extends BaseService<StockInMapper, StockIn> implements IStockInService,ApplicationContextAware {
	@Autowired
	private IStockInLineService stockInLineService;
	@Autowired
	private IStockStorageService stockStorageService;
	@Autowired
	private IPurchaseOrderLineService purchaseOrderLineService;
	@Autowired
	private IStockTransactionService stockTransactionService;
	@Autowired
	private IStockInConfirmService stockInConfirmService;
	@Autowired
	private ISaleReturnService saleReturnService;
	@Autowired
	private ISaleReturnLineService saleReturnLineService;
	private ApplicationContext applicationContext;
	@Autowired
	private DateUtil dateUtil;
	@Autowired
	private IIrDocTypeService irDocTypeService;
	@Autowired
	private IIrSequenceService irSequenceService;
	@Autowired
	private IPurchaseOrderService purchaseOrderService;
	@Autowired
	private IStockLocatorService stockLocatorService;
	@Override
	@Transactional
	public void prepareIt(Long id) {
		// TODO Auto-generated method stub
		List<StockInLine> stockInLineList=stockInLineService.getLineListByStockInId(id);
		if(stockInLineList==null ||stockInLineList.size()==0 ) {
			throw new RuntimeException("没有行明细");
		}
		
		List<StockInConfirm> confirmList=stockInConfirmService.getConfirmByStockInId(id);
		for(int i=0;i<confirmList.size();i++) {
			StockInConfirm stockInConfirm=confirmList.get(i);
			if(!"CO".equals(stockInConfirm.getDocStatus())) {
				throw new RuntimeException("请先完成入库确认单");
			}
		}
	}

	@Override
	@Transactional
	public void completeIt(Long id) {
		// TODO Auto-generated method stub
		StockIn stockIn=getById(id);
		stockIn.setDocStatus("CO");
		update(stockIn);
		if(!stockIn.getApproved()) {
			return;
		}
		List<StockInLine> stockInLineList=stockInLineService.getLineListByStockInId(id);
		for(int i=0;i<stockInLineList.size();i++) {
			StockInLine stockInLine=stockInLineList.get(i);
			BigDecimal movementQty=stockInLine.getMovementQty();
			stockStorageService.add(stockIn.getStockWarehouseId(), stockInLine.getStockLocatorId(), 
					stockInLine.getProductProductId(), stockInLine.getProductAttrSetInstanceId(), movementQty, null, null);
			Long purchaseOrderLineId=stockInLine.getPurchaseOrderLineId();
			if(purchaseOrderLineId!=null) {
				PurchaseOrderLine purchaseOrderLine=purchaseOrderLineService.getById(purchaseOrderLineId);
				BigDecimal qtyReserved=purchaseOrderLine.getQtyReserved();
				if(qtyReserved==null) {
					qtyReserved=new BigDecimal(0);
				}
				qtyReserved=qtyReserved.subtract(movementQty);
				purchaseOrderLine.setQtyReserved(qtyReserved);
				
				BigDecimal qtyDelivered=purchaseOrderLine.getQtyDelivered();
				if(qtyDelivered==null) {
					qtyDelivered=new BigDecimal(0);
				}
				qtyDelivered=qtyDelivered.add(movementQty);
				purchaseOrderLine.setQtyDelivered(qtyDelivered);
				purchaseOrderLineService.update(purchaseOrderLine);
				
				stockStorageService.add(stockIn.getStockWarehouseId(), stockInLine.getStockLocatorId(), 
						stockInLine.getProductProductId(), purchaseOrderLine.getProductAttrSetInstanceId(),null,null, movementQty.negate());
			}
			StockTransaction stockTransaction=new StockTransaction();
			String movementType="stockin";
			stockTransaction.setProductProductId(stockInLine.getProductProductId());
			stockTransaction.setStockLocatorId(stockInLine.getStockLocatorId());
			stockTransaction.setProductAttrSetInstanceId(stockInLine.getProductAttrSetInstanceId());
			stockTransaction.setMovementDate(stockIn.getMovementDate());
			stockTransaction.setMovementQty(movementQty);
			stockTransaction.setMovementType(movementType);
			stockTransaction.setStockInLineId(stockInLine.getId());
			stockTransactionService.insert(stockTransaction);
		}
	}

	@Override
	@Transactional
	public void approveIt(Long id) {
		// TODO Auto-generated method stub
		StockIn stockIn=getById(id);
		stockIn.setApproved(true);
		update(stockIn);
	}

	@Override
	@Transactional
	public void rejectIt(Long id) {
		// TODO Auto-generated method stub
		StockIn stockIn=getById(id);
		stockIn.setApproved(false);
		update(stockIn);
	}

	@Override
	@Transactional
	public void setDocStatus(Long id, String docStatus) {
		// TODO Auto-generated method stub
		StockIn stockIn=getById(id);
		stockIn.setDocStatus(docStatus);
		update(stockIn);
	}

	@Override
	@Transactional
	public StockIn generateReturnStockIn(Long saleReturnId) {
		// TODO Auto-generated method stub
		StockIn stockIn=new StockIn();
		SaleReturn saleReturn=saleReturnService.getById(saleReturnId);
		String docStatus=saleReturn.getDocStatus();
		if(!"CO".equals(docStatus)) {
			throw new RuntimeException("请先完成单据");
		}
		stockIn.setSaleReturnId(saleReturnId);
		stockIn.setMovementDate(dateUtil.getSqlNowDatetime());
		Long docTypeId=irDocTypeService.getIrDocTypeIdByCode("stockin");
		stockIn.setIrDocTypeId(docTypeId);
		stockIn.setDocumentNo(irSequenceService.getNextSequenceNo("stockin"));
		IStockOutService stockOutService=applicationContext.getBean(IStockOutService.class);
		StockOut stockOut=stockOutService.getById(saleReturn.getStockOutId());
		
		stockIn.setStockWarehouseId(stockOut.getStockWarehouseId());
		stockIn.setDocStatus("DR");
		stockIn.setResPartnerId(stockOut.getResPartnerId());
		stockIn.setResUserId(stockOut.getResUserId());
		stockIn.setResPartnerLocationId(stockOut.getResPartnerLocationId());
		insert(stockIn);
		
		List<SaleReturnLine> saleReturnLineList=saleReturnLineService.getLineListBySaleReturnId(saleReturnId);
		int lineNo=10;
		for(SaleReturnLine saleReturnLine:saleReturnLineList) {
			StockInLine stockInLine=new StockInLine();
			stockInLine.setSaleReturnLineId(saleReturnLine.getId());
			stockInLine.setLine(lineNo);
			IStockOutLineService stockOutLineService=applicationContext.getBean(IStockOutLineService.class);
			StockOutLine stockLoutLine=stockOutLineService.getById(saleReturnLine.getStockOutLineId());
			stockInLine.setProductProductId(saleReturnLine.getProductProductId());
			stockInLine.setProductAttrSetInstanceId(saleReturnLine.getProductAttrSetInstanceId());
			stockInLine.setUomUomId(saleReturnLine.getUomUomId());
			stockInLine.setStockLocatorId(stockLoutLine.getStockLocatorId());
			stockInLine.setQtyEntered(saleReturnLine.getQtyEntered());
			stockInLine.setStockInId(stockIn.getId());
			lineNo+=10;
			stockInLineService.insert(stockInLine);
		}
		return stockIn;
	}

	@Override
	public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
		// TODO Auto-generated method stub
		this.applicationContext=applicationContext;
	}

	@Override
	@Transactional
	public StockIn generateStockIn(Long purchaseOrderId) {
		// TODO Auto-generated method stub
		StockIn stockIn=new StockIn();
		PurchaseOrder purchaseOrder=purchaseOrderService.getById(purchaseOrderId);
		String docStatus=purchaseOrder.getDocStatus();
		if(!"CO".equals(docStatus)) {
			throw new RuntimeException("请先完成单据");
		}
		stockIn.setPurchaseOrderId(purchaseOrderId);
		stockIn.setMovementDate(dateUtil.getSqlNowDatetime());
		Long docTypeId=irDocTypeService.getIrDocTypeIdByCode("stockin");
		stockIn.setIrDocTypeId(docTypeId);
		stockIn.setStockWarehouseId(purchaseOrder.getStockWarehouseId());
		stockIn.setDocStatus("DR");
		stockIn.setResPartnerId(purchaseOrder.getResPartnerId());
		stockIn.setResUserId(purchaseOrder.getResUserId());
		stockIn.setResPartnerLocationId(purchaseOrder.getResPartnerLocationId());
		stockIn.setDocumentNo(irSequenceService.getNextSequenceNo("stockin"));
		insert(stockIn);
		
		List<PurchaseOrderLine> purchaseOrderLineList=purchaseOrderLineService.getLineListByPurchaseOrderId(purchaseOrderId);
		int lineNo=10;
		Long defaultLocatorId=stockLocatorService.getDefaultLocator(purchaseOrder.getStockWarehouseId()).getId();
		for(PurchaseOrderLine purchaseOrderLine:purchaseOrderLineList) {
			StockInLine stockInLine=new StockInLine();
			stockInLine.setPurchaseOrderLineId(purchaseOrderLine.getId());
			stockInLine.setLine(lineNo);
			stockInLine.setProductProductId(purchaseOrderLine.getProductProductId());
			stockInLine.setProductAttrSetInstanceId(purchaseOrderLine.getProductAttrSetInstanceId());
			stockInLine.setUomUomId(purchaseOrderLine.getUomUomId());
			stockInLine.setStockLocatorId(defaultLocatorId);
			stockInLine.setQtyEntered(purchaseOrderLine.getQtyEntered());
			stockInLine.setStockInId(stockIn.getId());
			lineNo+=10;
			stockInLineService.insert(stockInLine);
		}
		
		return stockIn;
	}
}